cmake_minimum_required(VERSION 3.10)
set(CMAKE_CXX_STANDARD 17)
project (python_rpc)
SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin/)

find_package(Python3 COMPONENTS Development REQUIRED)

IF (MSVC)
    foreach(var
        CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE
        CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO
        CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
        CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO
        )
        if(${var} MATCHES "/MD")
            string(REGEX REPLACE "/MD" "/MT" ${var} "${${var}}")
        endif()
    endforeach()
ELSE()
    if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
        set(CMAKE_CXX_COMPILER "clang++")
    elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU")
        set(CMAKE_CXX_COMPILER "g++")
    endif()
    find_program(CCACHE_PROGRAM ccache)
    if (CCACHE_PROGRAM)
        set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}")
    endif ()
ENDIF ()

aux_source_directory(${PROJECT_SOURCE_DIR}/../../thirdparty/src/jsoncpp SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../../thirdparty/src/kconfig/internal SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../../thirdparty/src/knet SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../util/python SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../detail/zookeeper SRC_LIST)

aux_source_directory(${PROJECT_SOURCE_DIR}/../../thirdparty/src/jsoncpp SDK_SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../../thirdparty/src/kconfig/internal SDK_SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../../thirdparty/src/knet SDK_SRC_LIST)
aux_source_directory(${PROJECT_SOURCE_DIR}/../util/python SDK_SRC_LIST)

add_library(rpc SHARED ${SRC_LIST})
add_library(rpc_sdk SHARED ${SDK_SRC_LIST})

target_compile_features(rpc PUBLIC cxx_std_17)
target_compile_features(rpc_sdk PUBLIC cxx_std_17)

IF (MSVC)
    set_target_properties(rpc PROPERTIES LINK_FLAGS "/ignore:4099")

    target_link_libraries(rpc PUBLIC
        ${Python3_LIBRARIES}
		debug ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/debug/zookeeper.lib optimized ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/release/zookeeper.lib
		debug ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/debug/hashtable.lib optimized ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/release/hashtable.lib
		debug ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/debug/libprotobufd.lib optimized ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/release/libprotobuf.lib	
		ws2_32.lib
	)
    
    set_target_properties(rpc_sdk PROPERTIES LINK_FLAGS "/ignore:4099")
    
    target_link_libraries(rpc_sdk PUBLIC
        ${Python3_LIBRARIES}
		debug ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/debug/libprotobufd.lib optimized ${PROJECT_SOURCE_DIR}/../../thirdparty/lib/win/release/libprotobuf.lib	
		ws2_32.lib
	)
else()
    link_directories(${PROJECT_SOURCE_DIR}/../thirdparty/lib/linux)
	target_link_libraries(rpc PUBLIC
        "$<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>:asan>"
        ${Python3_LIBRARIES}
		${PROJECT_SOURCE_DIR}/../../thirdparty/lib/linux/libprotobuf.a
		${PROJECT_SOURCE_DIR}/../../thirdparty/lib/linux/libzookeeper.a
		${PROJECT_SOURCE_DIR}/../../thirdparty/lib/linux/libhashtable.a
		-lpthread
		-ldl
	  )
    target_link_libraries(rpc_sdk PUBLIC
        ${Python3_LIBRARIES}
		${PROJECT_SOURCE_DIR}/../../thirdparty/lib/linux/libprotobuf.a
		-lpthread
		-ldl
	  )
endif()

#cross platfom file 
target_sources(rpc PRIVATE
	${PROJECT_SOURCE_DIR}/../util/time_util.cpp
    ${PROJECT_SOURCE_DIR}/../util/string_util.cpp
    ${PROJECT_SOURCE_DIR}/../util/os_util.cpp
	${PROJECT_SOURCE_DIR}/../box/box_channel.cpp
	${PROJECT_SOURCE_DIR}/../box/box_network.cpp
	${PROJECT_SOURCE_DIR}/../box/box_network_event.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/tcp_loop.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_channel.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_channel_loop.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_loop.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_socket.cpp
    ${PROJECT_SOURCE_DIR}/../box/loop/kcp/kcp_loop.cpp
	${PROJECT_SOURCE_DIR}/../config/box_config.cpp
	${PROJECT_SOURCE_DIR}/../detail/box_alloc.cpp
	${PROJECT_SOURCE_DIR}/../detail/box_config_impl.cpp
    ${PROJECT_SOURCE_DIR}/../detail/scheduler_impl.cpp
    ${PROJECT_SOURCE_DIR}/../detail/service_layer.cpp
    ${PROJECT_SOURCE_DIR}/../detail/rpc_probe_impl.cpp
    ${PROJECT_SOURCE_DIR}/../detail/call_tracer/call_tracer_factory_impl.cpp
    ${PROJECT_SOURCE_DIR}/../detail/call_tracer/reporter/call_tracer_zipkin_reporter.cpp
    ${PROJECT_SOURCE_DIR}/../detail/call_tracer/log/call_tracer_log.cpp
    ${PROJECT_SOURCE_DIR}/../detail/call_tracer/kafka/call_tracer_kafka.cpp
    ${PROJECT_SOURCE_DIR}/../detail/http_base_impl.cpp
    ${PROJECT_SOURCE_DIR}/../detail/http_data.cpp
	${PROJECT_SOURCE_DIR}/../util/object_pool.cpp
	${PROJECT_SOURCE_DIR}/../util/string_util.cpp
    ${PROJECT_SOURCE_DIR}/../util/time_system.cpp
    ${PROJECT_SOURCE_DIR}/../../thirdparty/src/kcp/ikcp.c
    ${PROJECT_SOURCE_DIR}/../../thirdparty/src/http_parser/http_parser.c
)

target_sources(rpc_sdk PRIVATE
	${PROJECT_SOURCE_DIR}/../util/time_util.cpp
    ${PROJECT_SOURCE_DIR}/../util/string_util.cpp
    ${PROJECT_SOURCE_DIR}/../util/os_util.cpp
	${PROJECT_SOURCE_DIR}/../box/box_channel.cpp
	${PROJECT_SOURCE_DIR}/../box/box_network.cpp
	${PROJECT_SOURCE_DIR}/../box/box_network_event.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/tcp_loop.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_channel.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_channel_loop.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_loop.cpp
	${PROJECT_SOURCE_DIR}/../box/loop/udp/udp_socket.cpp
    ${PROJECT_SOURCE_DIR}/../box/loop/kcp/kcp_loop.cpp
	${PROJECT_SOURCE_DIR}/../config/box_config.cpp
	${PROJECT_SOURCE_DIR}/../detail/box_alloc.cpp
	${PROJECT_SOURCE_DIR}/../detail/box_config_impl.cpp
    ${PROJECT_SOURCE_DIR}/../detail/scheduler_impl.cpp
	${PROJECT_SOURCE_DIR}/../util/object_pool.cpp
	${PROJECT_SOURCE_DIR}/../util/string_util.cpp
    ${PROJECT_SOURCE_DIR}/../../thirdparty/src/kcp/ikcp.c
)


#设置包含路径以及安装时候的路径
target_include_directories(rpc
	PUBLIC
	${PROJECT_SOURCE_DIR}
	${PROJECT_SOURCE_DIR}/..
	${PROJECT_SOURCE_DIR}/../../thirdparty 
	${PROJECT_SOURCE_DIR}/../../thirdparty/include 
	${PROJECT_SOURCE_DIR}/../../thirdparty/include/zookeeper
	${PROJECT_SOURCE_DIR}/../../thirdparty/include/lua
	${PROJECT_SOURCE_DIR}/../../thirdparty/include/rpc-backend-cpp
    ${PROJECT_SOURCE_DIR}/../../thirdparty/include/knet
    ${Python3_INCLUDE_DIRS}
    #cross-platform
    $<$<PLATFORM_ID:Windows>: ${PROJECT_SOURCE_DIR}/../../thirdparty/include/hiredis/win>
    $<$<PLATFORM_ID:Linux>:  ${PROJECT_SOURCE_DIR}/../../thirdparty/include/hiredis>
)

target_include_directories(rpc_sdk
	PUBLIC
	${PROJECT_SOURCE_DIR}
	${PROJECT_SOURCE_DIR}/..
	${PROJECT_SOURCE_DIR}/../../thirdparty 
	${PROJECT_SOURCE_DIR}/../../thirdparty/include 
	${PROJECT_SOURCE_DIR}/../../thirdparty/include/lua
	${PROJECT_SOURCE_DIR}/../../thirdparty/include/rpc-backend-cpp
    ${PROJECT_SOURCE_DIR}/../../thirdparty/include/knet
    ${Python3_INCLUDE_DIRS}
    #cross-platform
    $<$<PLATFORM_ID:Windows>: ${PROJECT_SOURCE_DIR}/../../thirdparty/include/hiredis/win>
    $<$<PLATFORM_ID:Linux>:  ${PROJECT_SOURCE_DIR}/../../thirdparty/include/hiredis>
)

target_compile_definitions(rpc PUBLIC
    DISABLE_SB_CODE DISABLE_CORO_CODE DISABLE_SB_LOG DISABLE_KNET_MEM_FUNC DISABLE_TRACE USE_STATIC_LIB THREADED SB_SDK
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Debug>>: _WINSOCK_DEPRECATED_NO_WARNINGS WIN32 _WINDOWS _DEBUG _CONSOLE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN>
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Release>>: _WINSOCK_DEPRECATED_NO_WARNINGS _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN WIN32 _WINDOWS NDEBUG>
)

target_compile_definitions(rpc_sdk PUBLIC
    DISABLE_SB_CODE DISABLE_SB_LOG DISABLE_KNET_MEM_FUNC DISABLE_TRACE USE_STATIC_LIB THREADED PYTHON_SDK SB_SDK
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Debug>>: _WINSOCK_DEPRECATED_NO_WARNINGS WIN32 _WINDOWS _DEBUG _CONSOLE _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN>
    $<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Release>>: _WINSOCK_DEPRECATED_NO_WARNINGS _CRT_SECURE_NO_WARNINGS WIN32_LEAN_AND_MEAN WIN32 _WINDOWS NDEBUG>
)

target_compile_options(rpc PUBLIC
    $<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Debug>>: -m64 -g -O0 -Wall -Wno-parentheses -Wno-deprecated-declarations -fnon-call-exceptions -fsanitize=address -fsanitize=leak -fno-omit-frame-pointer -fPIC>
    $<$<AND:$<PLATFORM_ID:Linux>,$<CONFIG:Release>>: -m64 -g -O2 -Wall -Wno-parentheses -Wno-deprecated-declarations -fnon-call-exceptions -fPIC>
	$<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Debug>>: /wd4706 /wd4206 /wd4100 /wd4244 /wd4127 /wd4702 /wd4324 /wd4310 /wd4820 /wd5033 /W4 /MP /EHa /Zi>
)

target_link_options(rpc PUBLIC 
	$<$<AND:$<PLATFORM_ID:Windows>,$<CONFIG:Debug>>: /NODEFAULTLIB:library /INCREMENTAL:NO>
)

target_compile_options(rpc_sdk PUBLIC 
	$<$<PLATFORM_ID:Windows>: /wd4706 /wd4206 /wd4100 /wd4244 /wd4127 /wd4702 /wd4324 /wd4310 /wd4820 /wd5033 /W4 /MP /EHa>
    $<$<PLATFORM_ID:Linux>: -m64 -g -O2 -Wall -Wno-parentheses -Wno-deprecated-declarations -fnon-call-exceptions -Wno-parentheses -fPIC>
)

IF (MSVC)
SET_TARGET_PROPERTIES(rpc PROPERTIES 
                    PREFIX ""
                    DEBUG_POSTFIX "_d"
                    SUFFIX ".pyd")
SET_TARGET_PROPERTIES(rpc_sdk PROPERTIES 
                    PREFIX ""
                    DEBUG_POSTFIX "_d"
                    SUFFIX ".pyd")
ELSE()
SET_TARGET_PROPERTIES(rpc PROPERTIES DEBUG_POSTFIX _d)
ENDIF()
                    
target_compile_definitions(rpc PUBLIC
$<$<CONFIG:Debug>: -DDEBUG -D_DEBUG>
$<$<CONFIG:Release>: -DRELEASE>
)

target_compile_definitions(rpc_sdk PUBLIC
$<$<CONFIG:Debug>: -DDEBUG -D_DEBUG>
$<$<CONFIG:Release>: -DRELEASE>
)

# TODO Windows平台区分debug,release版本
install(TARGETS rpc
	LIBRARY DESTINATION bin
)

install(TARGETS rpc_sdk
	LIBRARY DESTINATION bin/sdk
)